package club.emergency.wechat.question.operate.provider.impl;

import club.emergency.wechat.common.excel.XlsExcelProcess;
import club.emergency.wechat.common.response.ResponseEntity;
import club.emergency.wechat.common.response.StatusCode;
import club.emergency.wechat.common.utils.JsonConvert;
import club.emergency.wechat.exeception.common.CommonException;
import club.emergency.wechat.model.dictionary.DictionaryChild;
import club.emergency.wechat.model.option.ChoiceOption;
import club.emergency.wechat.model.question.Question;
import club.emergency.wechat.model.question.QuestionDailyRecord;
import club.emergency.wechat.persistence.dictionary.DictionaryChildMapper;
import club.emergency.wechat.persistence.option.ChoiceOptionMapper;
import club.emergency.wechat.persistence.question.QuestionMapper;
import club.emergency.wechat.question.operate.QuestionOperate;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.*;
import java.util.concurrent.ExecutorService;

/**
 * Create with IntelliJ IDEA
 * Project Name: wecaht
 * Package Name: club.emergency.wechat.question.operate.provider.impl
 * Date: 2018/11/28
 *
 * @author: 快乐的小菌菌
 * Description:
 */
@Slf4j
@RestController
public class QuestionOperateImpl implements QuestionOperate {

    private ExecutorService executorService;

    private QuestionMapper questionMapper;

    private ChoiceOptionMapper choiceOptionMapper;

    private DictionaryChildMapper dictionaryChildMapper;

    private PlatformTransactionManager platformTransactionManager;

    public QuestionOperateImpl(
            ExecutorService executorService,
            QuestionMapper questionMapper,
            ChoiceOptionMapper choiceOptionMapper,
            DictionaryChildMapper dictionaryChildMapper,
            PlatformTransactionManager platformTransactionManager
    ) {
        this.executorService = executorService;
        this.choiceOptionMapper = choiceOptionMapper;
        this.questionMapper = questionMapper;
        this.dictionaryChildMapper = dictionaryChildMapper;
        this.platformTransactionManager = platformTransactionManager;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String save(@RequestBody Question question, @RequestParam("choiceOptionList") String choiceOptionList) {
        List<ChoiceOption> choiceOptions = new JsonConvert<ChoiceOption>().jsonListDecode(choiceOptionList, ChoiceOption.class);
        questionMapper.insert(question);
        for (ChoiceOption choiceOption : choiceOptions) {
            choiceOption.setParentId(question.getId());
            choiceOptionMapper.insert(choiceOption);
        }
        return ResponseEntity.ok(StatusCode.DB_SAVE_OK, "新增题目、选项数据成功！", question.getId());
    }

    @Override
    public String saveFromExcel(@RequestParam("suffix") String suffix, @RequestBody byte[] bytes) {
        Map<Integer, List<String>> process;
        try {
            process = XlsExcelProcess.process(suffix, bytes, true);
        } catch (CommonException e) {
            return ResponseEntity.error(StatusCode.DB_SAVE_ERROR, e.getMessage());
        }
        List<Question> questionList = new ArrayList<>();
        for (int i = 2; i < process.size(); i++) {
            List<String> strings = process.get(i);
            //判断这一行的单元格是否正确，一共11个
            if (strings.size() != 11) {
                return ResponseEntity.ok(StatusCode.DB_SAVE_ERROR, "从Excel新增题目数据失败！请检查第" + (i + 1) + "行数据的单元格格数是否正确，请核对。");
            }
            //第一列，题目种类
            String num = strings.get(0);
            //第二列，题目种类
            String category = strings.get(1);
            //第三列，题干
            String content = strings.get(2);
            //第4列，题目类型
            String kind = strings.get(3);
            //第5列，正确答案
            String rightOption = strings.get(4);
            //第6列，A选项
            String optionA = strings.get(5);
            //第7列，B选项
            String optionB = strings.get(6);
            //第8列，C选项
            String optionC = strings.get(7);
            //第9列，D选项
            String optionD = strings.get(8);
            //第10列，E选项
            String optionE = strings.get(9);
            //第11列，F选项
            String optionF = strings.get(10);
            //判断当前行填写的数据是否有效是否
            if (Objects.isNull(num) ||
                    Objects.isNull(category) ||
                    Objects.isNull(content) ||
                    Objects.isNull(kind) ||
                    Objects.isNull(rightOption)) {
                log.info(num + "-" + category + "-" + content + "-" + kind + "-" + rightOption + "-");
                return ResponseEntity.ok(StatusCode.DB_SAVE_ERROR, "从Excel新增题目数据失败！请检查第" + (i + 1) + "行数据是否填写完整？");
            }
            //转化题目类型
            int kindNum = kind.equals("单选题") ? 0 : 1;
            //检查选择题的正确选项是否有对应的答案
            if (kindNum == 0) {
                if (Objects.isNull(optionA) ||
                        Objects.isNull(optionB)) {
                    return ResponseEntity.ok(StatusCode.DB_SAVE_ERROR, "从Excel新增题目数据失败！第" + (i + 1) + "行为选择题,选择题至少完整填写A、B两个选项");
                }
            }
            //检查判断题的正确选项是否有对应的答案
            if (kindNum == 1) {
                if (Objects.isNull(optionA) ||
                        Objects.isNull(optionB)) {
                    return ResponseEntity.ok(StatusCode.DB_SAVE_ERROR, "从Excel新增题目数据失败！第" + (i + 1) + "行为判断题，判断题至少完整填写A、B二个选项");
                }
            }
            //查询题目种类详情数据
            QueryWrapper<DictionaryChild> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("content", category);
            DictionaryChild dictionaryChild = dictionaryChildMapper.selectOne(queryWrapper);
            if (Objects.isNull(dictionaryChild)) {
                return ResponseEntity.ok(StatusCode.DB_SAVE_ERROR, "从Excel新增题目数据失败！请检查题目种类类型和字典列表数据是否一致，异常题目种类为：" + category);
            }
            //构建对象
            Question question = new Question();
            question.setCategoryAlias(dictionaryChild.getAlias());
            question.setCategory(category);
            question.setCategoryId(dictionaryChild.getId());
            question.setRightOption(rightOption);
            //选择正确选项内容
            switch (rightOption) {
                case "A":
                    question.setRightOptionContent(optionA);
                    break;
                case "B":
                    question.setRightOptionContent(optionB);
                    break;
                case "C":
                    question.setRightOptionContent(optionC);
                    break;
                case "D":
                    question.setRightOptionContent(optionD);
                    break;
                case "E":
                    question.setRightOptionContent(optionE);
                    break;
                case "F":
                    question.setRightOptionContent(optionF);
                    break;
                default:
                    break;
            }
            question.setContent(content);
            question.setKind(kindNum);
            //添加选项
            List<ChoiceOption> choiceOptionList = new ArrayList<>();
            //ascii码,从A开始
            int ascii = 65;
            //循环6次，A-F
            for (int j = 0; j < 6; j++) {
                ChoiceOption choiceOption = new ChoiceOption();
                choiceOption.setLetter(Character.toString((char) ascii++));
                //从A选项(单元格位置)开始
                String option = strings.get(5 + j);
                if (Objects.nonNull(option)) {
                    choiceOption.setContent(option);
                } else {
                    break;
                }
                choiceOptionList.add(choiceOption);
            }
            question.setChoiceOptionList(choiceOptionList);
            questionList.add(question);
        }
        //异步入库
        executorService.submit(() -> {
            log.info("Excel导入线程启动，试题添加中...");
            TransactionStatus transaction = platformTransactionManager.getTransaction(new DefaultTransactionDefinition());
            try {
                for (Question _question : questionList) {
                    questionMapper.insert(_question);
                    List<ChoiceOption> _choiceOptionList = _question.getChoiceOptionList();
                    for (ChoiceOption _choiceOption : _choiceOptionList) {
                        _choiceOption.setParentId(_question.getId());
                        choiceOptionMapper.insert(_choiceOption);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
                platformTransactionManager.rollback(transaction);
            }
            platformTransactionManager.commit(transaction);
            log.info("Excel导入线程结束，试题添加完毕！");
        });
        return ResponseEntity.ok(StatusCode.DB_SAVE_OK, "正在从Excel导入题目数据！请稍候...");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String modify(@RequestBody Question question, @RequestParam("choiceOptionList") String choiceOptionList) {
        List<ChoiceOption> choiceOptions = new JsonConvert<ChoiceOption>().jsonListDecode(choiceOptionList, ChoiceOption.class);
        questionMapper.updateById(question);
        for (ChoiceOption choiceOption : choiceOptions) {
            choiceOptionMapper.updateById(choiceOption);
        }
        return ResponseEntity.ok(StatusCode.DB_MODIFY_OK, "题目、选项数据修改成功！");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String remove(@RequestParam("id") Long id, @RequestParam(value = "choiceOptionIdList", required = false) String choiceOptionIdList) {
        List<String> idList = Arrays.asList(choiceOptionIdList.split(","));
        questionMapper.deleteById(id);
        choiceOptionMapper.deleteBatchIds(idList);
        return ResponseEntity.ok(StatusCode.DB_REMOVE_OK, "题目、选项数据删除成功!");
    }

    @Override
    public String checkCorrectForDaily(@RequestBody QuestionDailyRecord questionDailyRecord, @RequestParam("userOption") String userOption) {
        String result;
        if (questionDailyRecord.getRightOption().equals(userOption)) {
            result = ResponseEntity.ok(StatusCode.CHECK_OK, "判断日常答题选项正确", 1);
            return result;
        } else {
            result = ResponseEntity.ok(StatusCode.CHECK_ERROR, "题目回答错误", 0);
            return result;
        }
    }

}
